import { findDOM, compareTwoVdom } from "./react-dom";

export const updateQueue = {
  isBatchingUpdate: false, // 是否批量更新
  updaters: new Set(),
  batchUpdate() {
    // 设置不需要批量更新
    updateQueue.isBatchingUpdate = false;

    for (const updater of updateQueue.updaters) {
      updater.updateComponent();
    }
    updateQueue.updaters.clear();
  },
};

class Updater {
  constructor(classInstance) {
    this.classInstance = classInstance;
    this.pendingStates = []; // 存储变化后的状态，用于批量更新
    this.callbacks = [];
  }

  addState(partialState, callback) {
    this.pendingStates.push(partialState); // 等待更新的状态
    if (typeof callback === "function") {
      // 状态更新后的回调
      this.callbacks.push(callback);
    }

    this.emitUpdate();
  }

  emitUpdate(nextProps) {
    this.nextProps = nextProps;
    if (updateQueue.isBatchingUpdate) {
      // 需要批量更新
      updateQueue.updaters.add(this);
    } else {
      this.updateComponent();
    }
  }

  updateComponent() {
    if (this.nextProps || this.pendingStates.length > 0) {
      shouldUpdate(this.classInstance, this.nextProps, this.getState());
    }
  }

  getState() {
    let { state } = this.classInstance; // 获取旧实例的状态

    this.pendingStates.forEach((nextState) => {
      if (typeof nextState === "function") {
        nextState = nextState(state);
      }
      state = { ...state, ...nextState }; // 合并更新状态
    });

    this.pendingStates.length = 0;
    return state;
  }
}

function shouldUpdate(classInstance, nextProps, nextState) {
  // classInstance.state = nextState;
  // classInstance.forceUpdate();

  let willUpdate = true;
  if (
    classInstance.shouldComponentUpdate &&
    !classInstance.shouldComponentUpdate(nextProps, nextState)
  ) {
    // 设置不更新
    willUpdate = false;
  }
  if (willUpdate && classInstance.componentWillUpdate) {
    // 调用钩子函数
    classInstance.componentWillUpdate();
  }

  if (nextProps) {
    classInstance.props = nextProps;
  }

  classInstance.state = nextState;
  if (willUpdate) {
    // 更新视图
    classInstance.forceUpdate();
  }
}

export class Component {
  static isReactComponent = true;

  constructor(props) {
    this.props = props;

    this.state = {};
    this.updater = new Updater(this);
  }

  setState(partialState, callback) {
    this.updater.addState(partialState, callback);
  }

  // 去执行更新操作
  forceUpdate() {
    // 拿到 react-dom.js 中 mountClassComponent 和 mountFunctionComponent 方法中的 oldRenderVdom
    const oldRenderVdom = this.oldRenderVdom;
    // 根据虚拟DOM,拿到真实DOM
    const oldDOM = findDOM(oldRenderVdom);
    const newRenderVdom = this.render(); // 组件的 render 函数调用
    compareTwoVdom(oldDOM.parentNode, oldRenderVdom, newRenderVdom);

    // 更新 react-dom.js 中 mountClassComponent 和 mountFunctionComponent 方法中的 oldRenderVdom
    this.oldRenderVdom = newRenderVdom;

    if (this.componentDidUpdate) {
      // 执行钩子函数
      this.componentDidUpdate(this.props, this.state);
    }
  }
}
